<?php
/*
 * Main backups module
 * 
 * mod/backup/mod.backup.php
 * 
 * (c) Taras Kudla, t@ettera.com
 */
class mod_backup extends module {
	# table, where information about backups will store	
	private $table = "mod_backup";
	private $storedir = null;
	
	public function init(){
		$dir = $this->api->get("backupsdir");
		$dir = $this->api->parseasdir($dir);
		$this->storedir=$dir;
	}
	# creating system copy
	public function create(){	
		# global road parsing
		$this->api->base->addway("all",null,$this->lang->get("b1"));
		$this->api->base->addway("create",null,$this->lang->get("b2"));
		# checking for data input		
		if( $this->api->checkPOST("Submit")){
			$db = isset($_POST["db"]);
			$tpl = isset($_POST["tpl"]);
			$logs = isset($_POST["logs"]);
			$pub = isset($_POST["pub"]);
			$b = $this->makebackup($db,$logs,$pub,$tpl);
			if( !$b){
				$message = $this->api->errors->lastmessage();
				print $message;
			}
			else {
				# detecting file
				$file = $this->storedir.$b;
				# adding record to the database
				$this->api->dbo->insert($this->table,array("authorid"=>$this->api->user->getuserid(),
					"authoremail"=>$this->api->dbo->select("users","email","where id='".$this->api->user->getuserid()."' limit 1 offset 0",_RESULT_ONE),
					"created"=>date("Y-m-d H:i:s"),
					"totaldatasize"=>filesize($file),
					"filename"=>$b));
				# creating log record
				$this->api->log->write("System backup copy created");
				$this->api->redirect("all");
			}
		}
		$error = $this->benchmark()?null:$this->api->errors->lastmessage();		
		return $this->api->view->template("create",array("error"=>$error));
	}
	
	public function all(){
		return $this->api->view->template("all",array("data"=>$this->api->dbo->select($this->table,"*","order by id desc")));
	}
	# creating backup
	public function makebackup($db=true,$logs=true,$pubfiles=true,$tpl=true){
		if( !$this->benchmark()){
			return false;
		}		
		$name = "GepardAppBackup_".date("dMY_His");
		$copydir =$this->storedir.$name."/";
		# setting gepard into exception errors mode
		$tmp = $this->api->get("exceptiononerror");
		$this->api->set("exceptiononerror",true);
		try {		
		if( !is_dir($copydir))
			mkdir($copydir);	
		#preparing for schema creation
		$doc = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<schema>\n";
		# preparing for database storing
		if( $db == true){
		$dataservers = $this->api->dbo->getconnected();
		$db = array();
		foreach( $dataservers as $k=>$v){
			$db[$v]=&$this->api->dbo->$v;
		}
		# databases in schema
		foreach( $dataservers as $k=>$v){
			$doc .= "<database>\n\t<name>".$v."</name>\n";	
			# stroing all db tables
			$link = 	$db[$v];
			$dirname = $copydir."data_".$v."/";
			if( !is_dir($dirname))
				mkdir($copydir."data_".$v);
			$tables = $link->gettables();
			# preparing for tables backuping
			foreach( $tables as $key=>$table){
				$fields = $link->getfields($table);
				file_put_contents($dirname."table_$table.fields",serialize($fields));
				# preparing for datastoring
				$total = $link->select($table,"count(*) as total",null,_RESULT_ONE);
				$doc .="\t<table>\n\t\t<name>".$table."</name>\n\t\t<records>".$total."</records>\n\t\t<fields>".count($fields)."</fields>\n\t</table>\n";
				$steps=(int)round($total/10000+0.459)+1;
				for( $i=0;$i<$steps;$i++){
					$data = $link->select($table,"*","limit 10000 offset ".($i*10000));
					file_put_contents($dirname."table_$table.$i.data",serialize($data));
				}
			}
			$doc .="</database>\n";
		}
		}
		# preparing for logs storing
		if( $logs == true){
			$dirname =$copydir."logs/";
			if( !is_dir($dirname))
				mkdir($dirname);			
			$ldir = $this->api->parseasdir($this->api->get("logsdir"));
			$files = $this->api->file->getdirfiles($ldir);
			foreach( $files as $k=>$v){
				$file = $ldir.$v;
				if( is_dir($file))
				$this->api->file->copydir($file,$dirname.$v);
				else
				copy($file,$dirname.$v);
			}
			$doc .="<log>true</log>\n";
		}
		# preparing for logs storing
		if( $pubfiles == true){
			$dirname = $copydir."uploads/";
			if( !is_dir($dirname))
				mkdir($dirname);			
			$ldir = $this->api->parseasdir($this->api->get("uploadsdir"));
			$files = $this->api->file->getdirfiles($ldir);
			foreach( $files as $k=>$v){
				$file = $ldir.$v;
				if( is_dir($file))
				$this->api->file->copydir($file,$dirname.$v);
				else
				copy($file,$dirname.$v);
			}
			$doc .="<pubfiles>true</pubfiles>\n";
		}
		# preparing for templates storing
		if( $tpl == true){
			$dirname = $copydir."templates/";
			if( !is_dir($dirname))
				mkdir($dirname);			
			$ldir = $this->api->parseasdir($this->api->get("templatesdir"));
			$files = $this->api->file->getdirfiles($ldir);
			foreach( $files as $k=>$v){
				$file = $ldir.$v;
				if( is_dir($file))
				$this->api->file->copydir($file,$dirname.$v);
				else
				copy($file,$dirname.$v);
			}
			$doc .="<templates>true</templates>\n";
		}
		# writing additional data to schema
		$doc .="<user>\n\t<id>".$this->api->user->getuserid()."</id>\n</user>\n";
		$doc .="<date>".date("Y-m-d H:i:s")."</date>\n";
		$doc .="<version>".$this->api->GetKernelVersion()."</version>";
		$doc .= "\n</schema>";	
		file_put_contents($copydir."schema.xml",$doc);
		} catch ( GepardException $e ){
			$this->api->file->deletedir($copydir);
			$this->api->message("Cannot make backup, reason:".$e->getMessage());
			return false;
		}
		$this->api->set("exceptiononerror",$tmp);
		# preparing to archive
		$this->api->libload("archive");
		$tarname = $this->storedir.$name.".tar.gz";
		$backup = new gzip_file($tarname); 
		$backup->set_options(array('basedir' =>$copydir, 'overwrite' => 1, 'level' => 1)); 
		$backup->add_files(array("*")); 
		$backup->create_archive(); 
		$this->api->file->deletedir($copydir);
		return $name.".tar.gz";
	}
	# testing if can create backup copy
	public function benchmark(){
		if( !is_dir($this->storedir)){
			$this->api->message("Backups store directory doesnot exists ('".$this->storedir."')");
			return false;
		}
		if( !is_writable($this->storedir)){
			$this->api->message("Backups store directory is not writable ('".$this->storedir."')");
			return false;			
		}
		if( !extension_loaded("zlib")){
			$this->api->message("PHP extension 'Zlib' is not loaded");
			return false;			
		}
		return true;
	}
	
	public function install(){
		$table = new sqltable($this->table);		
		$table->addfield("id",_FIELD_INTAUTO);
		$table->addfield("authorid",_FIELD_INT);
		$table->addfield("authoremail",_FIELD_CHAR);
		$table->addfield("created",_FIELD_DATETIME);
		$table->addfield("totaldatasize",_FIELD_BIGINT);
		$table->addfield("filename",_FIELD_CHAR);
		$this->api->dbo->createtable($table);		
	}
	
	public function uninstall(){
		$this->api->dbo->droptable($this->table);
	}	
}
?>